<?php 
/**
 * Класс обеспечивает генерацию файлов sitemap
 *
 * @author Дмитрий Кузьма <kouzma.d@gmail.com>
 * @version 1.0
 */

class Service_Sitemap {


	protected $objSitemapFile = null;
	protected $objRobotsFile = null;
	
	protected $citiesSitemaped = 0;
	protected $stopSitemapping = false;
	/**
	 * Генерирует файл robots.txt
	 */
	public function generateRobotsTxt() {
		Service_Debug::setDebug();
		Service_Debug::$handDebugOff = true;
		$this->objRobotsFile = fopen(ABSPATH . 'robots.txt', 'w');
		if ($this->objRobotsFile === false) return false;
		$strRobots = "User-agent: *\n";
		$strRobots .= "Disallow: /auth\n";
		$strRobots .= "Allow: /\n";
		$strRobots .= "Crawl-delay: 2\n";        // Задержка между заугрзкой двух страниц
		$strRobots .= "Request-rate: 1/2\n";     // Загружать не более одной страницы за 2 секунды
		$strRobots .= "Host: www." . DOMAIN . "\n";
		//$strRobots .= "Visit-time: 0600-0845\n"; // Загружать страницы только в промежуток с 6 утра
    
		fwrite($this->objRobotsFile, $strRobots);
    $this->fillRobots();
    //$this->fillRobotsSitemaps();
		fclose($this->objRobotsFile);
	}
	
	/**
	 * Заполняет в robots.txt ссылки на sitemaps и создает эти sitemaps 
	 * 
	 */
	public function fillRobots() {
		Service_Debug::setDebug();
		// Генерируем по странам
		$obCountry = new Country();
		$arrCountries = $obCountry->find('all', array('select' => '`country_url`, `country_code`', 'order' => '`country_code` ASC'));
		if ($arrCountries) {
			foreach ($arrCountries as $arrCountry) {
				fwrite($this->objRobotsFile, 'Sitemap: ' . W_FULLPATH . 'content/sitemap/' . $arrCountry['country_code'] . ".xml\n");
			}
  	}
  	// Генерируем по статьям
  	fwrite($this->objRobotsFile, 'Sitemap: ' . W_FULLPATH . "content/sitemap/articles.xml\n");
	}
	
	/**
	 * Заполняет в robots.txt ссылки на sitemaps и создает эти sitemaps 
	 * 
	 */
	public function fillRobotsSitemaps() {
		Service_Debug::setDebug();
		
		// Генерируем по странам
		$obCountry = new Country();
		$arrCountries = $obCountry->find('all', array('select' => '`country_url`, `country_code`', 'order' => '`country_code` ASC'));
		if ($arrCountries) {
			foreach ($arrCountries as $arrCountry) {
				fwrite($this->objRobotsFile, 'Sitemap: ' . W_FULLPATH . 'content/sitemap/' . $arrCountry['country_code'] . ".xml\n");
				$this->generateCountrySitemap($arrCountry);
			}
  	}
  	
  	// Генерируем по статьям
  	fwrite($this->objRobotsFile, 'Sitemap: ' . W_FULLPATH . "content/sitemap/articles.xml\n");
  	$this->generateArticlesSitemap();
	}

	
	/**
	 * Генерирует sitemap
	 */
	public function generateSitemap() {
		Service_Debug::setDebug();
		$this->generateArticlesSitemap(); // Генерируем по статьям
		// Генерируем по странам
		$obCountry = new Country();
		$arrCountries = $obCountry->find('all', array('select' => '`country_url`, `country_code`', 'order' => '`sitemap_generated` ASC, `country_code` ASC'));
		if ($arrCountries) {
			foreach ($arrCountries as $arrCountry) {
				$this->generateCountrySitemap($arrCountry);
				if ($this->stopSitemapping) return false;
			}
  	}
	}
	
	/**
	 * Генерирует sitemap
	 */
	public function generateSitemapOld() {
		Service_Debug::setDebug();
		$this->objSitemapFile = fopen(ABSPATH . 'sitemap.xml', 'w');
		if ($this->objSitemapFile === false) return false;
		fwrite($this->objSitemapFile, $this->getSitemapOpen());
		  $this->fillAllUrls();
		fwrite($this->objSitemapFile, $this->getSitemapClose());
		fclose($this->objSitemapFile);
	}
	
	/**
	 * 
	 * Открывает sitemap
	 */
	public function getSitemapOpen() {
		Service_Debug::setDebug();
		return '<?xml version="1.0" encoding="UTF-8"?><urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">';
	}
	
	/**
	 * 
	 * Закрывает sitemap
	 */
	public function getSitemapClose() {
		Service_Debug::setDebug();
		return '</urlset>';
	}
	
	/**
	 * 
	 * Получает блок sitemap для одного url
	 * @param string $url - ссылка
	 * @param string $lastMod - дата последнего редактирования файла
	 * @param string $changeFreq - частота обновления (always/hourly/daily/weekly/monthly/yearly/never)
	 * @param string $priority - приоритет страницы
	 */
	public function getUrl($url, $lastMod = null, $changeFreq = null, $priority = '0.5') {
		Service_Debug::setDebug();
		$retStr = "<url>\n";
		  $retStr .= '<loc>' . Service_Escape::absolutelyEscapeString($url) . "</loc>\n";
		  if($lastMod) $retStr .= '<lastmod>' . $lastMod . "</lastmod>\n";
		  if($changeFreq) $retStr .= '<changefreq>' . $changeFreq . "</changefreq>\n";
		  if($priority) $retStr .= '<priority>' . $priority . "</priority>\n";
		$retStr .= "</url>\n";
		return $retStr;
	}

/*====================================================*/
/* Настройки конкретного сайта */
/*====================================================*/
	public function fillAllUrls() {
		Service_Debug::setDebug();
		fwrite($this->objSitemapFile, '');
	}
	
	/**
	 * Генерирует sitemap для конкретной страны
	 * 
	 * @param array $arrCountry - массив с информацией по стране
	 */
	public function generateCountrySitemap($arrCountry) {
		Service_Debug::setDebug();
		if (!$arrCountry) return false;
		$objCity = new City();
		$citiesAmount = $objCity->count("`city`.`country_code` = '" . $arrCountry['country_code'] . "'");
		if ($this->citiesSitemaped && $citiesAmount + $this->citiesSitemaped > 1000) {
			$this->stopSitemapping = true;
			return false;
		}
		else $this->citiesSitemaped += $citiesAmount;
		$this->objSitemapFile = fopen(ABSPATH . 'content/sitemap/' . $arrCountry['country_code'] . '.xml', 'w');
		if ($this->objSitemapFile === false) return false;
		fwrite($this->objSitemapFile, $this->getSitemapOpen());
		  
		  $strCountrySitemap = $this->getUrl(View_Country::getUrl($arrCountry, true, false, 'rus'), null, null, '0.8');
			$strCountrySitemap .= $this->getUrl(View_Country::getUrl($arrCountry, true, false, 'eng'), null, null, '0.8');
			fwrite($this->objSitemapFile, $strCountrySitemap);
			$this->fillCountryCitiesSitemap($arrCountry);
			$this->fillOldCountryCitiesSitemap($arrCountry);
			
		fwrite($this->objSitemapFile, $this->getSitemapClose());
		fclose($this->objSitemapFile);
		$objCountry = new Country($arrCountry['country_code']);
		$objCountry->updateField('sitemap_generated', Service_Date::gLocalTime2BD());
		
	}
	
	/**
	 * Заполняет карту сайта городами страны
	 * 
	 * @param array $arrCountry
	 */
	public function fillCountryCitiesSitemap($arrCountry) {
		Service_Debug::setDebug();
		$objCity = new City();
		$arrCities = $objCity->find('all', array('select' => '`country_url`, `city_url`', 'conditions' => "`country_code` = '" . $arrCountry['country_code'] . "'"));
		if (!$arrCities) return null;
		$sitemapStr = '';
		foreach ($arrCities as $arrCity) {
			$sitemapStr .= $this->getUrl(View_City::getUrl($arrCity, true, false, 'rus'), null, null, '0.6');
		  $sitemapStr .= $this->getUrl(View_City::getUrl($arrCity, true, false, 'eng'), null, null, '0.6');
			$sitemapStr .= $this->getUrl(View_City::getUrlAllHotels($arrCity, true, false, 'rus'), null, null, '0.3');
		  $sitemapStr .= $this->getUrl(View_City::getUrlAllHotels($arrCity, true, false, 'eng'), null, null, '0.3');
		}
		fwrite($this->objSitemapFile, $sitemapStr);
		$this->fillCountryHotelsSitemap($arrCountry);
	}
	
	/**
	 * Заполняет карту сайта городами страны из старой админки
	 * 
	 * @param array $arrCountry
	 */
	public function fillOldCountryCitiesSitemap($arrCountry) {
		Service_Debug::setDebug();
		$objDB = Service_Database::instance();
		$stmt = "SELECT `workname`
						 FROM `cities`
						 WHERE `ian_country_code` = '" . $arrCountry['country_code'] . "'";
		$arrCityUrls = $objDB->selectSimpleArray($stmt);
		if (!$arrCityUrls) return null;
		$sitemapStr = '';
		foreach ($arrCityUrls as $arrCityUrl) {
			$url = View_City::getOldUrl($arrCountry['country_url'], $arrCityUrl, true);
			$sitemapStr .= $this->getUrl(View_Base::getLanguageUrl($url, true, false, 'rus'), null, null, '0.6');
		  $sitemapStr .= $this->getUrl(View_Base::getLanguageUrl($url, true, false, 'eng'), null, null, '0.6');
		}
		fwrite($this->objSitemapFile, $sitemapStr);
		$this->fillCountryOldHotelsSitemap($arrCountry);
	}
	
	
	/**
	 * Заполняет карту сайта отелями
	 * 
	 * @param array $arrCountry
	 */
	public function fillCountryHotelsSitemap($arrCountry) {
		Service_Debug::setDebug();
		$objHotel = new Hotel();
		$arrHotels = $objHotel->find('all', array('select' => '`country_url`, `city_url`, `hotel_url`', 'conditions' => "`country_code` = '" . $arrCountry['country_code'] . "'"));
		if (!$arrHotels) return null;
		$sitemapStr = '';
		foreach ($arrHotels as $arrHotel) {
			$urlRu = View_Hotel::getUrl($arrHotel, true, false, 'rus');
			$urlEn = View_Hotel::getUrl($arrHotel, true, false, 'eng');
			if ($urlRu != '#') $sitemapStr .= $this->getUrl($urlRu, null, null, '0.4');
			if ($urlEn != '#') $sitemapStr .= $this->getUrl($urlEn, null, null, '0.4');
		}
		fwrite($this->objSitemapFile, $sitemapStr);
	}	
	
	/**
	 * Заполняет карту сайта отелями из старой админки
	 * 
	 * @param array $arrCountry
	 */
	public function fillCountryOldHotelsSitemap($arrCountry) {
		Service_Debug::setDebug();
		$objDB = Service_Database::instance();
		$stmt = "SELECT `cities`.`workname` AS 'city_url', `hotels`.`workname` AS 'hotel_url'
						 FROM `cities`
						 LEFT JOIN `hotels` ON `hotels`.`basic_country_id` = `cities`.`basic_country_id` AND `hotels`.`basic_city_id` = `cities`.`basic_city_id`
						 WHERE `cities`.`ian_country_code` = '" . $arrCountry['country_code'] . "'";
		$arrHotels = $objDB->select($stmt);
		if (!$arrHotels) return null;
		$sitemapStr = '';
		foreach ($arrHotels as $arrHotel) {
			$arrHotel['country_url'] = $arrCountry['country_url'];
			$urlRu = View_Hotel::getUrl($arrHotel, true, false, 'rus');
			$urlEn = View_Hotel::getUrl($arrHotel, true, false, 'eng');
			if ($urlRu != '#') $sitemapStr .= $this->getUrl($urlRu, null, null, '0.4');
			if ($urlEn != '#') $sitemapStr .= $this->getUrl($urlEn, null, null, '0.4');
		}
		fwrite($this->objSitemapFile, $sitemapStr);
	}

	
	/**
	 * Генерирует sitemap для статей
	 * 
	 */
	public function generateArticlesSitemap() {
		Service_Debug::setDebug();
		$this->objSitemapFile = fopen(ABSPATH . 'content/sitemap/articles.xml', 'w');
		if ($this->objSitemapFile === false) return false;
		fwrite($this->objSitemapFile, $this->getSitemapOpen());
		
		$objArticle = new Article();
  	$arrArticles = $objArticle->find('all', array('select' => 'url'));
		  
  	$sitemapStr = '';
		foreach ($arrArticles as $arrArticle) {
			$url = W_FULLPATH . $arrArticle['url'];
			$sitemapStr .= $this->getUrl(View_Base::getLanguageUrl($url, true, false, 'rus'), null, null, '0.4');
			$sitemapStr .= $this->getUrl(View_Base::getLanguageUrl($url, true, false, 'eng'), null, null, '0.4');
		}
		fwrite($this->objSitemapFile, $sitemapStr);
			
		fwrite($this->objSitemapFile, $this->getSitemapClose());
		fclose($this->objSitemapFile);
	}
	
  	
}
?>